package controllers

import (
	"context"
	"errors"
	"github.com/gin-gonic/gin"
	"go.didapinche.com/foundation/plat-echo/app/ops/models"
	"go.didapinche.com/foundation/plat-echo/app/ops/models/request"
	"go.didapinche.com/foundation/plat-echo/app/ops/services"
	"go.didapinche.com/foundation/plat-echo/pkg/constants"
	"go.uber.org/zap"
	"net/http"
	"strconv"
)

type TemplateController struct {
	service services.TemplateService
	logger  *zap.Logger
}

func NewTemplateController(service services.TemplateService, logger *zap.Logger) *TemplateController {
	return &TemplateController{
		service: service,
		logger:  logger,
	}
}

func (ctl *TemplateController) Create(c *gin.Context) {
	template := new(request.TemplateReq)
	if err := c.BindJSON(template); err != nil {
		ctl.logger.Error("parse id err", zap.Error(err))
		c.String(http.StatusBadRequest, "parse id err:%v", err)
		return
	}
	if err := ctl.service.Create(c.Request.Context(), template.Change()); err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call service Create err", zap.Error(err))
		c.String(http.StatusInternalServerError, "call service Create err:%v", err)
		return
	}
	c.JSON(http.StatusOK, "ok")
}

func (ctl *TemplateController) Update(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		ctl.logger.Error("parse id err", zap.Error(err))
		c.String(http.StatusBadRequest, "parse id err:%v", err)
		return
	}
	template := new(request.TemplateReq)
	template.ID = id
	if err := c.BindJSON(template); err != nil {
		ctl.logger.Error("bind json param error", zap.Error(err))
		c.String(http.StatusBadRequest, "bind json param error:%v", err)
		return
	}
	if err := ctl.service.Update(c.Request.Context(), template.Change()); err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call service Update error", zap.Error(err))
		c.String(http.StatusInternalServerError, "call service Update error:%v", err)
		return
	}
	c.JSON(http.StatusOK, "ok")
}

func (ctl *TemplateController) Delete(c *gin.Context) {
	id := c.Param("id")
	ID, err := strconv.ParseUint(id, 10, 64)
	if err != nil {
		ctl.logger.Error("parse id err", zap.Error(err))
		c.String(http.StatusBadRequest, "parse id err:%v", err)
		return
	}
	if err := ctl.service.Delete(c.Request.Context(), ID); err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call service Delete error", zap.Error(err))
		c.String(http.StatusInternalServerError, "call service Delete error:%v", err)
		return
	}
	c.JSON(http.StatusOK, "ok")
}

func (ctl *TemplateController) Find(c *gin.Context) {
	param := new(struct {
		TypeID   uint64 `form:"type_id"`
		Kind     uint64 `form:"template_type"`
		PageNum  int    `form:"page_num"`
		PageSize int    `form:"page_size"`
		Name     string `form:"name"`
	})
	err := c.BindQuery(param)
	if err != nil {
		ctl.logger.Error("bind  param error", zap.Error(err))
		c.String(http.StatusBadRequest, "bind  param error:%v", err)
		return
	}
	templates, count, err := ctl.service.Find(c.Request.Context(), param.Name, param.TypeID, param.Kind, param.PageSize, param.PageNum)
	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call service Find error", zap.Error(err))
		c.String(http.StatusInternalServerError, "call service Find error:%v", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"data":        templates,
		"total_count": count,
	})
}

func (ctl *TemplateController) FindUpdateApi(c *gin.Context) {
	param := new(request.TempUpdate)
	if err := c.BindQuery(param); err != nil {
		ctl.logger.Error("bind param error", zap.Error(err))
		c.String(http.StatusBadRequest, "bind param error:%v", err)
		return
	}
	TempID, _ := strconv.ParseUint(c.Query("temp_id"), 10, 64)
	param.TempID = TempID
	apiInfos, count, err := ctl.service.FindUpdateApi(c.Request.Context(), param)

	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call templateService.FindUpdateApi() error", zap.Error(err))
		c.String(http.StatusInternalServerError, "call templateService.FindUpdateApi() error:%v", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"data":        apiInfos,
		"total_count": count,
	})
}

func (ctl *TemplateController) FindUpdateApp(c *gin.Context) {
	param := new(request.TempUpdate)
	if err := c.BindQuery(param); err != nil {
		ctl.logger.Error("bind param error", zap.Error(err))
		c.String(http.StatusBadRequest, "bind param error:%v", err)
		return
	}
	TempID, _ := strconv.ParseUint(c.Query("temp_id"), 10, 64)
	param.TempID = TempID
	apps, count, err := ctl.service.FindUpdateApp(c.Request.Context(), param)

	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call templateService.FindUpdateApp() error", zap.Error(err))
		c.String(http.StatusInternalServerError, "call templateService.FindUpdateApp() error:%v", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"data":        apps,
		"total_count": count,
	})
}

func (ctl *TemplateController) FindUpdateHost(c *gin.Context) {
	param := new(request.TempUpdate)
	if err := c.BindQuery(param); err != nil {
		ctl.logger.Error("bind param error", zap.Error(err))
		c.String(http.StatusBadRequest, "bind param error:%v", err)
		return
	}
	TempID, _ := strconv.ParseUint(c.Query("temp_id"), 10, 64)
	param.TempID = TempID
	hosts, count, err := ctl.service.FindUpdateHost(c.Request.Context(), param)

	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call templateService.FindUpdateApi() error", zap.Error(err))
		c.String(http.StatusInternalServerError, "call templateService.FindUpdateApi() error:%v", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"data":        hosts,
		"total_count": count,
	})
}

func (ctl *TemplateController) Subscribe(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		ctl.logger.Error("parse id err", zap.Error(err))
		c.String(http.StatusBadRequest, "parse id err:%v", err)
		return
	}
	req := new(request.SubscribeReq)
	if err := c.BindJSON(req); err != nil {
		ctl.logger.Error("bind params error", zap.Error(err))
		c.String(http.StatusBadRequest, "bind params error:%v", err)
		return
	}
	req.ID = id

	err = ctl.service.Subscribe(c.Request.Context(), req)
	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call service Subscribe error", zap.Error(err))
		c.String(http.StatusInternalServerError, err.Error())
		return
	}

	c.JSON(http.StatusOK, "ok")
}

func (ctl *TemplateController) GetProgress(c *gin.Context) {
	progress, err := ctl.service.GetProgress(c.Request.Context())
	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		c.String(http.StatusInternalServerError, err.Error())
		return
	}
	c.JSON(http.StatusOK, progress)
}

//查询app下所有tag
func (ctl *TemplateController) FindSlaMetrics(c *gin.Context) {
	labels, err := ctl.service.FindSla(c.Request.Context())
	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		c.String(http.StatusInternalServerError, "call SlaService.FindSlaMetrics() error:%v", err)
		return
	}
	c.JSON(http.StatusOK, labels)
}

func (ctl *TemplateController) Preview(c *gin.Context) {
	template := new(request.TemplateReq)
	if err := c.BindJSON(template); err != nil {
		ctl.logger.Error("parse id error", zap.Error(err))
		c.String(http.StatusBadRequest, "parse id error:%v", err)
		return
	}
	graph, err := ctl.service.Preview(c.Request.Context(), template.Change())
	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call service Preview error", zap.Error(err))
		c.String(http.StatusInternalServerError, "call service Preview error:%v", err)
		return
	}
	c.JSON(http.StatusOK, graph)
}

//查询预览的app，api，host
func (ctl *TemplateController) FindByKey(c *gin.Context) {
	params := new(struct {
		PageNum  int              `form:"page_num"`
		PageSize int              `form:"page_size"`
		Kind     models.GraphKind `form:"kind"`
		Name     string           `form:"name"`
	})
	if err := c.BindQuery(params); err != nil {
		ctl.logger.Error("bind params error", zap.Error(err))
		c.String(http.StatusBadRequest, "bind params error:%v", err)
		return
	}
	if params.PageNum == 0 {
		params.PageNum = 1
	}
	if params.PageSize == 0 {
		params.PageSize = 10
	}
	record, total, err := ctl.service.FindByKey(c.Request.Context(), params.Kind, params.Name, params.PageNum, params.PageSize)
	if err != nil {
		if errors.Is(err, context.Canceled) {
			ctl.logger.Error("context canceled", zap.Error(err))
			c.Status(constants.StatusRequestCanceled)
			return
		}
		ctl.logger.Error("call service FindByKey error", zap.Error(err))
		c.String(http.StatusInternalServerError, "call accessRecordService.FindByUID() error:%v", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"data":        record,
		"total_count": total,
	})
}
